
#include <string.h>
#include "../lib/data_pool.h"

uint8_t data_pool_init(DATA_POOL_STRUCT* data_pool,
					uint8_t* buffer, uint16_t buffer_len, uint8_t data_size)
{
	if((data_pool == 0)||(buffer == 0)||(buffer_len == 0)
		||(data_size < 2)||(data_size > buffer_len)){
		return 0;
	}

	buffer_len = buffer_len/data_size;
	buffer_len = buffer_len*data_size;

	data_pool->data_pool_buffer = buffer;
	data_pool->data_pool_len = buffer_len;
	data_pool->data_size = data_size;
	data_pool->add_p = 0;
	data_pool->del_p = data_pool->add_p+1;		//empty

	return 1;
}

uint8_t* data_pool_get_data_piont(DATA_POOL_STRUCT* data_pool, uint16_t data_serial_num)	//data_serial_num:0~0xfffe
{
	uint16_t read_p;

	if(data_pool == 0){
		return 0;
	}

	if(data_serial_num >= data_pool_check_data_num(data_pool)){
		return 0;
	}

//	read_p = (data_serial_num*(data_pool->data_size)) + data_pool->del_p;
//	if(read_p >= data_pool->data_pool_len){
//		read_p -= data_pool->data_pool_len;
//	}
	read_p = data_serial_num*(data_pool->data_size);
	if(read_p >= (data_pool->data_pool_len - data_pool->del_p)){
		read_p -= (data_pool->data_pool_len - data_pool->del_p);
	}
	else{
		read_p += data_pool->del_p;
	}

	return (uint8_t*)&(data_pool->data_pool_buffer[read_p]);
}

uint8_t data_pool_read_data(DATA_POOL_STRUCT* data_pool,
							uint16_t data_serial_num, uint8_t* read_buffer, uint8_t* read_data_len)	//data_serial_num:0~0xfffe
{
	uint16_t read_p;

	if((data_pool == 0)||(read_buffer == 0)){
		return 0;
	}

	if(data_serial_num >= data_pool_check_data_num(data_pool)){
		return 0;
	}

//	read_p = (data_serial_num*(data_pool->data_size)) + data_pool->del_p;
//	if(read_p >= data_pool->data_pool_len){
//		read_p -= data_pool->data_pool_len;
//	}
	read_p = data_serial_num*(data_pool->data_size);
	if(read_p >= (data_pool->data_pool_len - data_pool->del_p)){
		read_p -= (data_pool->data_pool_len - data_pool->del_p);
	}
	else{
		read_p += data_pool->del_p;
	}

	(*read_data_len) = data_pool->data_pool_buffer[read_p];
	if((*read_data_len) > (data_pool->data_size)-1){
		(*read_data_len) = (data_pool->data_size)-1;
	}
	memcpy(read_buffer, &(data_pool->data_pool_buffer[read_p+1]),
			(*read_data_len));

	return 1;
}

uint8_t data_pool_write_data(DATA_POOL_STRUCT* data_pool,
								uint8_t* write_data, uint8_t write_data_len)	//write_data_len <= data_size - 1
{
	if((data_pool == 0)||(write_data == 0)){
		return 0;
	}

	if(write_data_len+1 > data_pool->data_size){
		return 0;
	}

	if(data_pool->add_p == data_pool->del_p+1){		//full
		return 0;
	}

	if(data_pool->del_p == data_pool->add_p+1){		//empty
		data_pool->del_p -= 1;
	}

	data_pool->data_pool_buffer[data_pool->add_p] = write_data_len;
	memcpy(&(data_pool->data_pool_buffer[data_pool->add_p+1]), write_data,
			(write_data_len));


//	data_pool->add_p += data_pool->data_size;
//	if(data_pool->add_p >= data_pool->data_pool_len){
//		data_pool->add_p = 0;
//	}
	if(data_pool->add_p >= (data_pool->data_pool_len - data_pool->data_size)){
		data_pool->add_p = 0;
	}
	else{
		data_pool->add_p += data_pool->data_size;
	}

	if(data_pool->add_p == data_pool->del_p){		//full
		data_pool->add_p += 1;
	}

	return 1;
}

uint8_t data_pool_del_data(DATA_POOL_STRUCT* data_pool)
{
	if(data_pool == 0){
		return 0;
	}

	if(data_pool->del_p == data_pool->add_p+1){		//empty
		return 0;
	}

	if(data_pool->add_p == data_pool->del_p+1){		//full
		data_pool->add_p -= 1;
	}

//	data_pool->del_p += data_pool->data_size;
//	if(data_pool->del_p >=  data_pool->data_pool_len){
//		data_pool->del_p = 0;
//	}
	if(data_pool->del_p >= (data_pool->data_pool_len - data_pool->data_size)){
		data_pool->del_p = 0;
	}
	else{
		data_pool->del_p += data_pool->data_size;
	}

	if(data_pool->del_p == data_pool->add_p){		//empty
		data_pool->del_p += 1;
	}

	return 1;
}

uint8_t data_pool_check_empty(DATA_POOL_STRUCT* data_pool)
{
	if(data_pool == 0){
		return 0XFF;
	}

	if(data_pool->del_p == data_pool->add_p+1){		//empty
		return 1;
	}
	else{
		return 0;
	}
}

uint8_t data_pool_check_full(DATA_POOL_STRUCT* data_pool)
{
	if(data_pool == 0){
		return 0XFF;
	}

	if(data_pool->add_p == data_pool->del_p+1){		//full
		return 1;
	}
	else{
		return 0;
	}
}

uint16_t data_pool_check_data_num(DATA_POOL_STRUCT* data_pool)
{
	uint16_t num;

	if(data_pool == 0){
		return 0xffff;
	}

	if(data_pool->del_p == data_pool->add_p+1){		//empty
		return 0;
	}

	if(data_pool->add_p == data_pool->del_p+1){		//full
		num = data_pool->data_pool_len/data_pool->data_size;
		return num;
	}

	if(data_pool->add_p > data_pool->del_p){
		num = data_pool->add_p - data_pool->del_p;
		num = num/(data_pool->data_size);
	}
	else if(data_pool->add_p < data_pool->del_p){
		num = (data_pool->data_pool_len - data_pool->del_p) + data_pool->add_p;
		num = num/(data_pool->data_size);
	}
	else{	//(data_pool->del_p == data_pool->add_p){		//error
		num = 0xffff;
	}

	return num;
}

uint8_t data_pool_clr_all(DATA_POOL_STRUCT* data_pool)
{
	if(data_pool == 0){
		return 0;
	}

	data_pool->add_p = 0;
	data_pool->del_p = data_pool->add_p+1;		//empty
	return 1;
}
